import os
import pandas as pd
import numpy as np
import logging

class SPIFileParser:
    """SPI文件解析工具类，用于解析SPI数据文件并返回结构化数据"""

    def __init__(self, target_model=None):
        """初始化解析器

        Args:
            target_model: 可选，指定目标机种，如果提供则只处理该机种的文件
        """
        self.target_model = target_model
        self.logger = self._setup_logger()

    def _setup_logger(self):
        """设置日志记录器"""
        logger = logging.getLogger('SPIFileParser')
        if not logger.handlers:
            handler = logging.StreamHandler()
            formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
            handler.setFormatter(formatter)
            logger.addHandler(handler)
            logger.setLevel(logging.INFO)
        return logger

    def parse_file(self, file_path):
        """解析SPI文件并返回机种信息和原始数据

        Args:
            file_path: SPI文件路径

        Returns:
            tuple: (机种名称, 数据DataFrame, 列索引字典) 如果解析失败则返回 (None, None, None)
        """
        try:
            with open(file_path, 'r') as f:
                lines = f.readlines()

            # 提取机种信息
            if len(lines) < 2:
                self.logger.warning(f"文件 {file_path} 行数不足，无法提取机种信息")
                return None, None, None

            model_line = lines[1].strip().split(',')
            if len(model_line) < 1:
                self.logger.warning(f"文件 {file_path} 无法提取机种信息")
                return None, None, None

            model_name = model_line[0]
            line_number = model_line[1] if len(model_line) > 1 else "未知"

            # 如果指定了目标机种且不匹配，则跳过
            if self.target_model is not None and model_name != self.target_model:
                self.logger.info(f"跳过非目标机种文件: {os.path.basename(file_path)}, 机种: {model_name}")
                return model_name, None, None

            self.logger.info(f"正在处理机种文件: {os.path.basename(file_path)}, 机种: {model_name}, 线号: {line_number}")

            # 读取表头
            headers_line = lines[4].strip() if len(lines) > 4 else ""
            headers = headers_line.split(',')

            # 读取数据行
            data_rows = []
            for i in range(5, len(lines)):
                if lines[i].strip():  # 忽略空行
                    row = lines[i].strip().split(',')
                    data_rows.append(row)

            # 创建数据框
            df = pd.DataFrame(data_rows)

            if len(df) == 0:
                self.logger.warning(f"文件 {file_path} 没有有效数据行")
                return model_name, None, None

            # 定位关键列的索引
            height_col = None
            area_col = None
            volume_col = None

            # 根据表头查找列
            for i, header in enumerate(headers):
                if 'Height' in header and height_col is None:
                    height_col = i
                elif 'Area(%)' in header and area_col is None:
                    area_col = i
                elif 'Volume(%)' in header and volume_col is None:
                    volume_col = i

            # 如果找不到特定列，使用默认索引
            if height_col is None:
                height_col = 4  # 通常是第5列
            if area_col is None:
                area_col = 3  # 通常是第4列
            if volume_col is None:
                volume_col = 5  # 通常是第6列

            # 返回机种名称、数据和列索引
            column_indices = {
                'height_col': height_col,
                'area_col': area_col,
                'volume_col': volume_col
            }

            return model_name, df, column_indices

        except Exception as e:
            self.logger.error(f"解析文件 {file_path} 时出错: {str(e)}")
            return None, None, None

    def process_file(self, file_path):
        """处理SPI文件并提取统计数据

        Args:
            file_path: SPI文件路径

        Returns:
            tuple: (机种名称, 结构化数据字典) 如果处理失败则返回 (None, None)
        """
        try:
            # 解析文件
            model_name, df, columns = self.parse_file(file_path)

            # 如果不是目标机种或解析失败，则跳过
            if model_name is None or df is None or columns is None:
                return model_name, None

            # 提取时间信息作为板子ID
            file_name = os.path.basename(file_path)
            board_id = file_name.split('_')[0]

            # 提取列索引
            height_col = columns['height_col']
            area_col = columns['area_col']
            volume_col = columns['volume_col']

            # 转换为数值型
            df[height_col] = pd.to_numeric(df[height_col], errors='coerce')
            df[height_col] = df[height_col] * 1000

            df[area_col] = pd.to_numeric(df[area_col], errors='coerce')
            df[volume_col] = pd.to_numeric(df[volume_col], errors='coerce')

            # 计算关键指标的平均值
            height_avg = df[height_col].mean()
            area_avg = df[area_col].mean()
            volume_avg = df[volume_col].mean()

            # 计算关键指标的标准差
            height_std = df[height_col].std(ddof=1)  # ddof=1使用样本标准差
            area_std = df[area_col].std(ddof=1)
            volume_std = df[volume_col].std(ddof=1)

            # 创建结构化数据
            structured_data = {
                'id': board_id,
                'height_avg': height_avg,
                'area_avg': area_avg,
                'volume_avg': volume_avg,
                'height_std': height_std,
                'area_std': area_std,
                'volume_std': volume_std,
                'raw_data': df  # 包含原始数据
            }

            return model_name, structured_data

        except Exception as e:
            self.logger.error(f"处理文件 {file_path} 时出错: {str(e)}")
            return None, None

    def get_latest_files(self, folder_path, file_pattern="_P.csv", max_count=100):
        """获取指定文件夹中最新的文件

        Args:
            folder_path: 文件夹路径
            file_pattern: 文件匹配模式
            max_count: 最大文件数量

        Returns:
            list: 文件路径列表
        """
        try:
            self.logger.info(f"正在搜索 {folder_path} 中的SPI数据文件...")
            files = []

            # 列出所有符合条件的文件
            for file_name in os.listdir(folder_path):
                if file_pattern in file_name:
                    file_path = os.path.join(folder_path, file_name)
                    # 获取文件修改时间
                    mod_time = os.path.getmtime(file_path)
                    files.append((file_path, mod_time))

            if not files:
                self.logger.warning(f"在 {folder_path} 中未找到符合条件的文件")
                return []

            # 按修改时间排序
            files.sort(key=lambda x: x[1], reverse=True)
            self.logger.info(f"找到 {len(files)} 个SPI数据文件，正在筛选最新的 {max_count} 个文件")

            # 返回最新的max_count个文件
            newest_files = [f[0] for f in files[:max_count]]
            return newest_files

        except Exception as e:
            self.logger.error(f"获取文件列表时出错: {str(e)}")
            return []
